# -*- coding: utf-8 -*-
import numpy
import json
from sklearn.neighbors import KNeighborsClassifier as kNN
import circle_cal

global rssi_group
with open('rssi_group2.json', 'r') as f:
    global rssi_array
    rssi_list = json.loads(f.read())
    rssi_group = numpy.array(rssi_list)

global rssi_labels
with open('rssi_labels2.json', 'r') as f:
    global rssi_array
    rssi_list = json.loads(f.read())
    rssi_labels = numpy.array(rssi_list)

rssi_group_size = 10  # = len(rssi_group[0])
print('rssi_group:%d' % len(rssi_group))
print('rssi_group_size:%d' % rssi_group_size)
print('rssi_labels:%d' % len(rssi_labels))

# 构建KNN分类器
neigh = kNN(n_neighbors=3, weights='uniform', algorithm='auto')
# 拟合模型，trainingMat为测试矩阵,hwLabels为对应的标签
neigh.fit(rssi_group, rssi_labels)


def get_distance(rssi_num):
    def deal_rssi(rssi_list):
        result = [0] * (-30 + 100 + 1)  # -30~-100
        for item in rssi_list:
            if item > -30:
                item = -30
            if item < -100:
                item = -100
            result[100 + item] = item
        result_sum = sum(result)
        for i in range(len(result)):
            result[i] = round(result[i] / float(result_sum), 3)
        num = (max(result) + min(list(filter(lambda x: x > 0, result)))) / 3.0
        return [0 if (item < num) else 1 for item in result]

    # print(rssi_num)
    rssi_num = numpy.array(deal_rssi(rssi_num)).reshape((1, -1))
    # print(rssi_num)
    # 获得预测结果
    classifierResult = neigh.predict(rssi_num)
    return classifierResult


def get_distance2(rssi_num):
    def cal(num):
        num = -0.008778245 * num ** 3 \
              - 2.158676003 * num ** 2 \
              - 177.065725 * num \
              - 4840.7079785
        if num < 0:
            num = 0
        if num > 20:
            num = -1
        return num

    result = [cal(num) for num in rssi_num]
    return result


def get_location(route_data_list, type=None):
    def cal_num(num1, num2):
        return num1 * num1 - num2 * num2

    # location = [[0, 0, 4.5], [10, 0, 74.5], [0, 10, 74.5], [2, 2, 0.5], [3, 3, 4.5], [4, 4, 12.5]]
    location = route_data_list
    location_len = len(location)
    A = numpy.empty((location_len - 1, 2))
    for i in range(location_len - 1):
        A[i][0] = 2 * (location[i][0] - location[location_len - 1][0])
        A[i][1] = 2 * (location[i][1] - location[location_len - 1][1])
    b = numpy.empty((location_len - 1, 1))
    for i in range(location_len - 1):
        b[i][0] = cal_num(location[i][0], location[location_len - 1][0]) \
                  + cal_num(location[i][1], location[location_len - 1][1]) \
                  + cal_num(location[location_len - 1][2], location[i][2])
    A = numpy.mat(A)
    b = numpy.mat(b)
    X = (A.T * A).I * A.T * b
    if type is None:
        return X[0, 0], X[1, 0]
    else:
        return type(X[0, 0]), type(X[1, 0])


def test():
    rssi_group_test = None
    with open('rssi_group2_test.json', 'r') as f:
        global rssi_array
        rssi_list = json.loads(f.read())
        rssi_group_test = numpy.array(rssi_list)

    rssi_labels_test = None
    with open('rssi_labels2_test.json', 'r') as f:
        global rssi_array
        rssi_list = json.loads(f.read())
        rssi_labels_test = numpy.array(rssi_list)
    err_num = 0
    all_num = len(rssi_group_test)
    for i in range(0, all_num):
        if len(rssi_group_test[i]) != rssi_group_size:
            print("rssi_group_size error %d" % i)
        # print(get_distance(rssi_group_test[i]),rssi_labels_test[i])
        if get_distance(rssi_group_test[i]) != rssi_labels_test[i]:
            err_num += 1
        # print(get_distance(rssi_group[i]),i//(all_num//10))
    print('错误率：%0.3f%%(%d/%d)' % (err_num * 100 / all_num, err_num, all_num))


def test2():
    err_num = 0
    all_num = len(rssi_group)
    for i in range(0, all_num):
        if len(rssi_group[i]) != rssi_group_size:
            print("rssi_group_size error %d" % i)
        if get_distance(rssi_group[i]) != rssi_labels[i]:
            err_num += 1
        # print(get_distance(rssi_group[i]),i//(all_num//10))
    print('错误率：%0.3f%%(%d/%d)' % (err_num * 100 / all_num, err_num, all_num))


# test() #有训练集、测试集
# test2() #只有训练集
# test_data=[0]*71
# test_data[100-80]=1
# print(get_distance(test_data))
# print(get_distance(rssi_group[1234]))
# print(get_distance2([num for num in range(-100, -50)]))
global route_list
route_list = None


def location_init(route_list_param):
    global route_list
    route_list = route_list_param
    for item in route_list:
        item.append(-1)


# 获取路由距离排序
def get_route_order(rssi_list):
    rssi_item_length = []
    rssi_item_max = []
    for i in range(len(rssi_list)):
        rssi_item_length.append((i, len(rssi_list[i])))
        if len(rssi_list[i]) != 0:
            rssi_item_max.append((i, max(rssi_list[i])))
        else:
            rssi_item_max.append((i, -100))
    rssi_item_length.sort(key=lambda temp: temp[1], reverse=True)  # 根据百分比排序降序
    rssi_item_max.sort(key=lambda temp: temp[1], reverse=True)  # 根据百分比排序降序
    # print(rssi_item_length)
    # print(rssi_item_max)
    return rssi_item_max


# for test
# get_route_order([[5, 6], [1, 2, 3], [7, 8, 9]])
'''
def location_measure(rssi_list):
    if route_list is None:
        return None
    route_data_list = []
    if isinstance(rssi_list, list) and isinstance(rssi_list[0], list):
        if len(rssi_list) == len(route_list):
            for i in range(len(rssi_list)):
                item = rssi_list[i]
                distance = []
                if len(item) > 0:
                    if len(item) == 20 or True:
                        distance = get_distance(item)
                        # print('distance type1')
                    else:
                        distance = get_distance2(item)
                        # print('distance type2')
                if len(distance) > 0 and distance[0] >= 0:
                    route_list[i][2] = distance[0]
                    route_data_list.append(route_list[i])
                else:
                    route_list[i][2] = -1
    if len(route_data_list) > 0:
        # print(route_data_list)
        if len(route_data_list) >= 3:
            return get_location(route_data_list), 0, 0, len(route_data_list)
        elif len(route_data_list) == 2:
            return circle_cal.cal(route_data_list[0][0], route_data_list[0][1],
                                  route_data_list[1][0], route_data_list[1][1],
                                  route_data_list[0][2], route_data_list[1][2]), \
                   0, 0, 2
        else:
            return (route_data_list[0][0], route_data_list[0][1], route_data_list[0][2]), 0, 0, 1
    return None
'''


def location_measure(rssi_list):
    if route_list is None:
        return None
    route_data_list = []
    if isinstance(rssi_list, list) and isinstance(rssi_list[0], list):
        if len(rssi_list) == len(route_list):
            for i in range(len(rssi_list)):
                item = rssi_list[i]
                distance = []
                if len(item) > 0:
                    if len(item) == 20 or True:
                        distance = get_distance(item)
                        # print('distance type1')
                    else:
                        distance = get_distance2(item)
                        # print('distance type2')
                if len(distance) > 0 and distance[0] >= 0:
                    route_list[i][2] = distance[0]
                    route_data_list.append(route_list[i])
                else:
                    route_list[i][2] = -1
    return route_list

# print(get_distance(list(range(-40, -30))))
# print(get_distance([-40]*100))
# print(get_distance([-50]*100))
# print(get_distance([-60]*100))
# print(get_distance([-70]*100))
# print(get_distance([-80]*100))
# print(get_distance([-90]*100))

# location_init([[1, 1], [2, 2], [3, 3]])
# print(location_measure([[], [], [-40] * 100]))
# print(route_list[2][2])
